AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )


util.PrecacheSound( "explode_9" )
--util.PrecacheSound( "NPC_SScanner.Gib" )
util.PrecacheSound( "ambient/levels/labs/electric_explosion4.wav" )
util.PrecacheSound( "ambient/levels/labs/electric_explosion3.wav" )
util.PrecacheSound( "ambient/levels/labs/electric_explosion1.wav" )
--util.PrecacheSound( "weapons/mortar/mortar_explode3.wav" )
util.PrecacheSound( "ambient/explosions/exp2.wav" )
--util.PrecacheSound( "PortableThumper.ThumpSound" )
util.PrecacheSound( "k_lab.ambient_powergenerators" )
util.PrecacheSound( "ambient/machines/thumper_startup1.wav" )
util.PrecacheSound( "coast.siren_citizen" )
util.PrecacheSound( "common/warning.wav" )

include('shared.lua')
local Nuke = false
local Ground = 1 + 0 + 2 + 8 + 32
local Energy_Increment = 1000
local Coolant_Increment = 80
local Hydrogen_Increment = 80
local HasFuel = false --does it have a hydrogen source?

function ENT:Initialize()
	self.Entity:PhysicsInit( SOLID_VPHYSICS )
	self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
	self.Entity:SetSolid( SOLID_VPHYSICS )
	
	local phys = self.Entity:GetPhysicsObject()
	self.val1 = 0
	self.val2 = 0
	self.overdrive = 0
	self.overdrivefactor = 0 --will  be the same as overdrive but I'm to lazy to modify it
	self.damaged = 0
	self.critical = 0
	
	self.fuel = false
	self.coolant = false
	
	if not (WireAddon == nil) then self.Inputs = Wire_CreateInputs(self.Entity, { "On", "Overdrive" }) end
	if not (WireAddon == nil) then self.Outputs = Wire_CreateOutputs(self.Entity, { "Out" }) end

	self.Entity:SetColor( 10, 96, 255, 255 )
	self.timer = CurTime() +  1
	if (phys:IsValid()) then
		phys:Wake()
		phys:SetMass(3000)
		
	end
end

function ENT:Setup()
	self:TriggerInput("On", 0)
end

function ENT:TriggerInput(iname, value)
	if (iname == "On") then
		if (value ~= 0) then
			if ( self.Active == 0 ) then
				self.Active = 1
				self.Entity:EmitSound( "k_lab.ambient_powergenerators" )
				self.Entity:EmitSound( "ambient/machines/thumper_startup1.wav" )
				Wire_TriggerOutput(self.Entity, "Out", self.Active)
			end
		else
			if ( self.Active == 1 ) then
				self.Active = 0
				Wire_TriggerOutput(self.Entity, "Out", self.Active)
			end
		end
	elseif (iname == "Overdrive") then
		if (value > 0) then
			if ( self.Active == 1 ) then
			end
			self.overdrive = 1
			self.Entity:EmitSound( "k_lab.ambient_powergenerators" )
			self.Entity:EmitSound( "ambient/machines/thumper_startup1.wav" )
			self.overdrivefactor = value
		else
			if ( self.Active == 1 ) then
			end
			self.overdrive = 0
		end
	end
end

function ENT:Use()
end

function ENT:Damage()
	if (self.damaged == 0) then
		self.damaged = 1
	end
end

function ENT:Repair()
	self.Entity:SetColor( 10, 96, 255, 255 )
	self.health = self.max_health
	self.damaged = 0
	self.critical = 0
	self.Entity:StopSound( "coast.siren_citizen" )
end

function ENT:Destruct()
	if Nuke == true then --oh shit
		if (RD_GetResourceAmount(self, "energy") < 100000) then
	
		local function Func1(Entity)
			if Entity:IsValid() then
				local Effect = EffectData()
					Effect:SetOrigin(Entity:GetPos() + Vector( math.random(-60, 60), math.random(-60, 60), math.random(-60, 60) ))
					Effect:SetScale(1)
					Effect:SetMagnitude(25)
					util.Effect("Explosion", Effect, true, true)
			end
		end
		local function Func2(Entity)
			if Entity:IsValid() then
				local Effect = EffectData()
					Effect:SetOrigin(Entity:GetPos())
					Effect:SetScale(3)
					Effect:SetMagnitude(100)
					util.Effect("Explosion", Effect, true, true)

					Entity:Remove()
			end
		end
		timer.Simple(1, Func1, self.Entity)
		timer.Simple(1.2, Func1, self.Entity)
		timer.Simple(2, Func1, self.Entity)
		timer.Simple(2, Func2, self.Entity)
	else
		local effectdata = EffectData()
		effectdata:SetMagnitude( 1 )
		
		local Pos = self.Entity:GetPos()
	
		effectdata:SetOrigin( Pos )
		effectdata:SetScale( 23000 )
		util.Effect( "warpcore_breach", effectdata )
		local tAllPlayers = player.GetAll()
		for _, pPlayer in pairs( tAllPlayers ) do
			pPlayer.Entity:EmitSound( "explode_9" )
		end
		self:EmitSound( "explode_9" )
		
		local blastradius = 3000
		
		local attached=duplicator.GetAllConstrainedEntitiesAndConstraints( self.Entity, {},{} ) or {}
		attached[self.Entity:EntIndex()]=self.Entity
		
		
		for _,Ent in pairs(attached) do
			if Ent != self.Entity then
				if (string.find(Ent.Entity:GetClass(),"prop") ~= nil) then
					local delay = (math.random(300, 700) / 100)
					Ent.Entity:SetKeyValue("exploderadius","1")  
					Ent.Entity:SetKeyValue("explodedamage","1")  
					Ent.Entity:Fire("break","",tostring(delay)) 
					Ent.Entity:Fire("kill","",tostring(delay + 1)) 
					Ent.Entity:Fire("enablemotion","",0) --bye bye fort that took you 4 hours to make
					constraint.RemoveAll(Ent.Entity)
				end
			
			end
		end
		
		
		
		for key,found in pairs(ents.FindInSphere(Pos,blastradius)) do
			movetype = 	found:GetMoveType()
			if (movetype == 2 or movetype == 3 or movetype == 5 or movetype == 6 or movetype == 8 or movetype == 9) then
				local entpos = found:LocalToWorld(found:OBBCenter()) --more accurate than getpos
				local vecang = entpos - Pos
				if vecang.z < 0 then vecang.z = 0 end
				vecang:Normalize()
			
				if found:IsNPC() then --ugh, messy
					util.BlastDamage(self.Entity, self.Owner, found:GetPos(), 256, 512)
				elseif found:IsPlayer() then
					found:SetModel("models/player/charple01.mdl")
					util.BlastDamage(self.Entity, self.Owner, found:GetPos(), 256, 512)
				elseif found:IsValid() then
					
					local physobj = found:GetPhysicsObject()
					local mass = 1
					if(physobj:IsValid()) then
						mass = physobj:GetMass();
					end
					
					if (found:GetMoveType() ~= 6) or not physobj:IsValid() then --if it's not a physics object...
						found:SetVelocity(vecang*(170*mass)) --push it away
					elseif (string.find(found:GetClass(),"ragdoll") ~= nil) then --if it's a ragdoll...
						physobj:ApplyForceCenter(vecang*(8e4*mass)) --push it away anyway :D
					else -- if it is a physics object...
						physobj:ApplyForceOffset(vecang*(8e4*mass),entpos + Vector(math.random(-20,20),math.random(-20,20),math.random(20,40))) --still push it away
					end
					
					util.BlastDamage(self.Entity, self.Owner, Pos - vecang*64, 384, 1000) --splode it
				end
			end
		end
		
		local shake = ents.Create("env_shake")
		shake:SetKeyValue("amplitude", "16")
		shake:SetKeyValue("duration", "6")
		shake:SetKeyValue("radius", 1) 
		shake:SetKeyValue("spawnflags", 5) 
		shake:SetKeyValue("frequency", "240")
		shake:SetPos(Pos)
		shake:Spawn()
		shake:Fire("StartShake","","0.6")
		shake:Fire("kill","","8")
		
		--shatter all glass
		for k,v in pairs(ents.FindByClass("func_breakable_surf")) do
			local dist = (v:GetPos() - Pos):Length()
			v:Fire("Shatter","",dist/19e3)
		end
		
		for k,v in pairs(ents.FindByClass("func_breakable")) do
			local dist = (v:GetPos() - Pos):Length()
			v:Fire("break","",dist/19e3)
		end
		Msg( "should have removed!\n" )
		self.Entity:Remove()
	end
	else --feww
		local function Func1(Entity)
			if Entity:IsValid() then
				local Effect = EffectData()
					Effect:SetOrigin(Entity:GetPos() + Vector( math.random(-60, 60), math.random(-60, 60), math.random(-60, 60) ))
					Effect:SetScale(1)
					Effect:SetMagnitude(25)
					util.Effect("Explosion", Effect, true, true)
			end
		end
		local function Func2(Entity)
			if Entity:IsValid() then
				local Effect = EffectData()
					Effect:SetOrigin(Entity:GetPos())
					Effect:SetScale(3)
					Effect:SetMagnitude(100)
					util.Effect("Explosion", Effect, true, true)

					Entity:Remove()
			end
		end
		timer.Simple(1, Func1, self.Entity)
		timer.Simple(1.2, Func1, self.Entity)
		timer.Simple(2, Func1, self.Entity)
		timer.Simple(2, Func2, self.Entity)
		self.Entity:Remove()
	end
end

function ENT:OnRemove()
	Dev_Unlink_All(self.Entity)
	self.Entity:StopSound( "k_lab.ambient_powergenerators" )
	self.Entity:StopSound( "coast.siren_citizen" )
	
end


function ENT:Output()
	return 1
end

function ENT:Extract_Energy()
	local inc = Energy_Increment
	if ( self.overdrive > 0 ) then
		inc = math.Round(inc * self.overdrivefactor)
		if self.overdrivefactor > 3 then
			self:Destruct()
		else
			if self.overdrive > 1 then
				DamageLS(self, math.random(0, math.Round(self.overdrivefactor*3)))
			end
		end
	end
	if (self.critical == 1) then
		local ang = self.Entity:GetAngles()
		local pos = (self.Entity:GetPos() + (ang:Up() * self.Entity:BoundingRadius()))
		local test = math.random(1, 10)
		if (test <= 2) then
			zapme((pos + (ang:Right() * 90)), 5)
			zapme((pos - (ang:Right() * 90)), 5)
			self.Entity:EmitSound( "ambient/levels/labs/electric_explosion3.wav" )
			inc = 0
		elseif (test <= 4) then
			zapme((pos + (ang:Right() * 90)), 3)
			zapme((pos - (ang:Right() * 90)), 3)
			self.Entity:EmitSound( "ambient/levels/labs/electric_explosion4.wav" )
			inc = math.ceil(inc / 4)
		elseif (test <= 6) then
			zapme((pos + (ang:Right() * 90)), 2)
			zapme((pos - (ang:Right() * 90)), 2)
			self.Entity:EmitSound( "ambient/levels/labs/electric_explosion1.wav" )
			inc = math.ceil(inc / 2)
		end
	end
	
	if (self.coolant) then
		RD_SupplyResource(self, "energy", inc)
	end
	
	local QuickHack = self.overdrive --just to make sure it uses resources
	if (QuickHack == 0) then
		QuickHack = 1 --make it run on standered
	end
	
	--coolant check
	if (RD_GetResourceAmount(self, "coolant") <= math.Round(QuickHack*Coolant_Increment)) then
		DamageLS(self.Entity, 10)
		
		local Smoke = ents.Create("env_smoketrail")
		Smoke:SetKeyValue("opacity", 1)
		Smoke:SetKeyValue("spawnrate", 10)
		Smoke:SetKeyValue("lifetime", 2)
		Smoke:SetKeyValue("startcolor", "180 180 180")
		Smoke:SetKeyValue("endcolor", "255 255 255")
		Smoke:SetKeyValue("minspeed", 15)
		Smoke:SetKeyValue("maxspeed", 30)
		Smoke:SetKeyValue("startsize", (self.Entity:BoundingRadius() / 2))
		Smoke:SetKeyValue("endsize", self.Entity:BoundingRadius())
		Smoke:SetKeyValue("spawnradius", 10)
		Smoke:SetKeyValue("emittime", 300)
		Smoke:SetKeyValue("firesprite", "sprites/firetrail.spr")
		Smoke:SetKeyValue("smokesprite", "sprites/whitepuff.spr")
		Smoke:SetPos(self.Entity:GetPos())
		Smoke:SetParent(self.Entity)
		Smoke:Spawn()
		Smoke:Activate()
		Smoke:Fire("kill","", 1)
		if (self.critical == 0) then self.Entity:EmitSound( "common/warning.wav" ) end
		self.coolant = false
	else
		RD_ConsumeResource(self, "coolant", math.Round(QuickHack*Coolant_Increment))
		self.coolant = true
	end
	
	if (RD_GetResourceAmount(self, "hydrogen") <= math.Round(QuickHack*Hydrogen_Increment)) then
		if (self.critical == 0) then self.Entity:EmitSound( "common/warning.wav" ) end
		self.fuel = false
	else
		RD_ConsumeResource(self, "hydrogen", math.Round(QuickHack*Hydrogen_Increment))
		self.fuel = true
	end
	

	return
end



function ENT:Think()
	if ( self.Active == 0 ) then
		self:SetOverlayText( "Fusion Reactor\n(OFF)\nCoolant: " .. self.val1.."\n Hydrogen: "..self.val2)
	else
		if (self.overdrive > 0) then
			self:SetOverlayText( "Fusion Reactor\n(ON)\n(OVERDRIVE)\nCoolant: " .. self.val1.."\n Hydrogen: "..self.val2)
		else
			self:SetOverlayText( "Fusion Reactor\n(ON)\nCoolant: " .. self.val1.."\n Hydrogen: "..self.val2)
		end
	end
	if ( self.timer > CurTime() ) then return end
	if (self.Active == 1) then
		self:Extract_Energy()
	end
	if (self.damaged == 1) then
		if (RD_GetResourceAmount(self, "energy") >= 100000) then
			if (self.critical == 0) then
				self.Entity:EmitSound( "coast.siren_citizen" )
				self.critical = 1
			end
		else
			if (self.critical == 1) then
				self.Entity:StopSound( "coast.siren_citizen" )
				self.critical = 0
			end
		end
	end
	self.val1 = RD_GetResourceAmount(self, "coolant")
	self.val2 = RD_GetResourceAmount(self, "hydrogen")
	self.timer = CurTime() +  1
end


function ENT:AcceptInput(name,activator,caller)
	if name == "Use" and caller:IsPlayer() and caller:KeyDownLast(IN_USE) == false then
		if ( self.Active == 0 ) then
			self.Active = 1
			self.Entity:EmitSound( "k_lab.ambient_powergenerators" )
			self.Entity:EmitSound( "ambient/machines/thumper_startup1.wav" )
			
			if not (WireAddon == nil) then Wire_TriggerOutput(self.Entity, "Out", 1) end
		else
			self.Active = 0
			self.Entity:StopSound( "k_lab.ambient_powergenerators" )
			if not (WireAddon == nil) then Wire_TriggerOutput(self.Entity, "Out", 0) end
		end
	end
end


function ENT:PreEntityCopy()
	RD_BuildDupeInfo(self.Entity)
	if (WireAddon == 1) then
		local DupeInfo = Wire_BuildDupeInfo(self.Entity)
		if DupeInfo then
			duplicator.StoreEntityModifier( self.Entity, "WireDupeInfo", DupeInfo )
		end
	end
end

function ENT:PostEntityPaste( Player, Ent, CreatedEntities )
	RD_ApplyDupeInfo(Ent, CreatedEntities)
	if (WireAddon == 1) then
		if (Ent.EntityMods) and (Ent.EntityMods.WireDupeInfo) then
			Wire_ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, function(id) return CreatedEntities[id] end)
		end
	end
end
